/* Includes ------------------------------------------------------------------*/
#include <string.h>
#include "uart.h"
#include "stm32f1xx_ll_rcc.h"
#include "stm32f1xx_ll_bus.h"
#include "stm32f1xx_ll_gpio.h"
#include "stm32f1xx_ll_usart.h"

/* Private macros ------------------------------------------------------------*/
#define UART_MAX_PORT_NUM				5
#define UART(x)							UART ## x
#define USART(x)						USART ## x
#define UART_ENABLE_CLOCK(x)			UART ## x ## _EnableClock
#define UART_CONFIGURE_GPIO(x)			UART ## x ## _ConfigureGPIO	
#define UART_IRQN(x)					UART ## x ## _IRQn
#define USART_IRQN(x)					USART ## x ## _IRQn


/* Private types -------------------------------------------------------------*/
typedef struct
{
	USART_TypeDef *pxUARTx;
	void (*UARTx_EnableClock)();
	void (*UARTx_ConfigureGPIO)();
	IRQn_Type ulUARTx_IRQn;
} UART;

typedef struct
{
	void (*pFuncRxneHandler)(void);
	void (*pFuncIdleHandler)(void);
	void (*pFuncTxeHandler)(void);
	void (*pFuncTcHandler)(void);
} UART_Handler;

/* Private functions ---------------------------------------------------------*/
static void UART1_EnableClock(void);
static void UART1_ConfigureGPIO(void);
static void UART2_EnableClock(void);
static void UART2_ConfigureGPIO(void);
#if defined(USART3)
static void UART3_EnableClock(void);
static void UART3_ConfigureGPIO(void);
#endif
#if defined(UART4)
static void UART4_EnableClock(void);
static void UART4_ConfigureGPIO(void);
#endif
#if defined(UART5)
static void UART5_EnableClock(void);
static void UART5_ConfigureGPIO(void);
#endif

/* Private constants ---------------------------------------------------------*/
static const UART g_xUART[UART_MAX_PORT_NUM + 1] = 
{
	//index 0, NULL
	{NULL},	
	{USART(1), UART_ENABLE_CLOCK(1), UART_CONFIGURE_GPIO(1), USART_IRQN(1)},
	{USART(2), UART_ENABLE_CLOCK(2), UART_CONFIGURE_GPIO(2), USART_IRQN(2)},
#if defined(USART3)
	{USART(3), UART_ENABLE_CLOCK(3), UART_CONFIGURE_GPIO(3), USART_IRQN(3)},
#else 
	{NULL},
#endif
#if defined(UART4)
	{UART(4), UART_ENABLE_CLOCK(4), UART_CONFIGURE_GPIO(4), UART_IRQN(4)},
#else
	{NULL},
#endif
#if defined(UART5)
	{UART(5), UART_ENABLE_CLOCK(5), UART_CONFIGURE_GPIO(5), UART_IRQN(5)}
#else
	{NULL}
#endif
};

/* Exported user handlers ----------------------------------------------------*/
static UART_Handler g_xUARTHandler[UART_MAX_PORT_NUM + 1];

/**
  * @brief  UART Init
  * @param  ulPort: 1, 2, 3, 4, 5
  * @param  ulBaudRate: UARTx Baudrate
  * @param  ulParity: UARTx Parity
  * @retval None
  */
void UARTx_Init(unsigned long ulPort, unsigned long ulBaudRate, unsigned long ulParity, unsigned long ulStopBits)
{
	LL_USART_InitTypeDef LL_UART_InitStructure;
	
	if (ulPort > UART_MAX_PORT_NUM || g_xUART[ulPort].pxUARTx == NULL)
		return;
	
	//UART CLK Enable
	g_xUART[ulPort].UARTx_EnableClock();
	//GPIO Configure
	g_xUART[ulPort].UARTx_ConfigureGPIO();
	//Disbale USART
	LL_USART_Disable(g_xUART[ulPort].pxUARTx);
	//DeInit
	LL_USART_StructInit(&LL_UART_InitStructure);
	//Initialize
	LL_UART_InitStructure.BaudRate 				= ulBaudRate;
	LL_UART_InitStructure.StopBits 				= ulStopBits << 12;
	switch (ulParity)
	{
		case UART_PARITY_NONE:
			LL_UART_InitStructure.Parity		= LL_USART_PARITY_NONE;
			LL_UART_InitStructure.DataWidth 	= LL_USART_DATAWIDTH_8B;
			break;
		case UART_PARITY_EVEN:
			LL_UART_InitStructure.Parity		= LL_USART_PARITY_EVEN;
			LL_UART_InitStructure.DataWidth 	= LL_USART_DATAWIDTH_9B;
			break;
		case UART_PARITY_ODD:
			LL_UART_InitStructure.Parity		= LL_USART_PARITY_ODD;
			LL_UART_InitStructure.DataWidth 	= LL_USART_DATAWIDTH_9B;
			break;
	}
	LL_UART_InitStructure.OverSampling			= LL_USART_OVERSAMPLING_16;
	LL_UART_InitStructure.HardwareFlowControl	= LL_USART_HWCONTROL_NONE;
	LL_UART_InitStructure.TransferDirection 	= LL_USART_DIRECTION_TX_RX;
	LL_USART_Init(g_xUART[ulPort].pxUARTx, &LL_UART_InitStructure);
	
	//Enable UART
	LL_USART_Enable(g_xUART[ulPort].pxUARTx);
}

/**
  * @brief  UART IT Configure
  * @param  ulPort: 1, 2, 3, 4, 5
  * @param  bIdle: IT_IDLE
  * @param  bTxe: IT_TXE
  * @param  bTc: IT_TC
  * @param  bRxne: IT_RXNE
  * @retval None
  */
void UARTx_EnableIT(unsigned long ulPort, bool bIdle, bool bTxe, bool bTc, bool bRxne)
{
	if (ulPort > UART_MAX_PORT_NUM || g_xUART[ulPort].pxUARTx == NULL)
		return;
	
	bIdle 	== true ? LL_USART_EnableIT_IDLE(g_xUART[ulPort].pxUARTx) 	: LL_USART_DisableIT_IDLE(g_xUART[ulPort].pxUARTx);
	bTxe 	== true ? LL_USART_EnableIT_TXE(g_xUART[ulPort].pxUARTx) 	: LL_USART_DisableIT_TXE(g_xUART[ulPort].pxUARTx);
	bTc 	== true ? LL_USART_EnableIT_TC(g_xUART[ulPort].pxUARTx) 	: LL_USART_DisableIT_TC(g_xUART[ulPort].pxUARTx);
	bRxne 	== true ? LL_USART_EnableIT_RXNE(g_xUART[ulPort].pxUARTx) 	: LL_USART_DisableIT_RXNE(g_xUART[ulPort].pxUARTx);
}

/**
  * @brief  UART IT Configure
  * @param  ulPriority: UART IT Priority
  * @retval None
  */
void UARTx_SetPriority(unsigned long ulPort, unsigned long ulPriority)
{
	if (ulPort > UART_MAX_PORT_NUM || g_xUART[ulPort].pxUARTx == NULL)
		return;
	
	NVIC_SetPriority(g_xUART[ulPort].ulUARTx_IRQn, ulPriority);  
	NVIC_EnableIRQ(g_xUART[ulPort].ulUARTx_IRQn);
}

/**
  * @brief  UART Send Data (Blocked)
  * @param  ulPort: 1, 2, 3, 4, 5
  * @param  pucData: Data pointer
  * @param  ulLen: Length of data
  * @retval None
  */
void UARTx_Send(unsigned long ulPort, unsigned char * pucData, unsigned long ulLen)
{
	unsigned long i;
	
	if (ulPort > UART_MAX_PORT_NUM || g_xUART[ulPort].pxUARTx == NULL)
		return;
	
	for (i = 0;i < ulLen;i++)
	{
		LL_USART_TransmitData8(g_xUART[ulPort].pxUARTx, pucData[i]);
		//Wait until TXE flag
		while (!LL_USART_IsActiveFlag_TXE(g_xUART[ulPort].pxUARTx));
	}
	//Wait for TC flag
	while (!LL_USART_IsActiveFlag_TC(g_xUART[ulPort].pxUARTx));
}


/**
  * @brief  UART Send Data (None Blocked for IT)
  * @param  ulPort: 1, 2, 3, 4, 5
  * @param  ucData: Data
  * @retval None
  */
void UARTx_SendToDR(unsigned long ulPort, unsigned char ucData)
{
	if (ulPort > UART_MAX_PORT_NUM || g_xUART[ulPort].pxUARTx == NULL)
		return;
	
	LL_USART_TransmitData8(g_xUART[ulPort].pxUARTx, ucData);
}

/**
  * @brief  UART Receive Data
  * @param  ulPort: 1, 2, 3, 4, 5
  * @retval received data
  */
unsigned char UARTx_Receive(unsigned long ulPort)
{
	if (ulPort > UART_MAX_PORT_NUM || g_xUART[ulPort].pxUARTx == NULL)
		return 0;
	
	return LL_USART_ReceiveData8(g_xUART[ulPort].pxUARTx);
}

/**
  * @brief  UART set call back function
  * @param  ulPort: 1, 2, 3, 4, 5
  * @retval received data
  */
void UARTx_SetCallBack(unsigned long ulPort, void (*pFuncIdleCallBack)(void), void (*pFuncTxeCallBack)(void), void (*pFuncTcCallBack)(void), void (*pFuncRxneCallBack)(void))
{
	if (ulPort > UART_MAX_PORT_NUM || g_xUART[ulPort].pxUARTx == NULL)
		return;
	
	g_xUARTHandler[ulPort].pFuncIdleHandler = pFuncIdleCallBack;
	g_xUARTHandler[ulPort].pFuncTxeHandler	= pFuncTxeCallBack;
	g_xUARTHandler[ulPort].pFuncTcHandler	= pFuncTcCallBack;
	g_xUARTHandler[ulPort].pFuncRxneHandler	= pFuncRxneCallBack;
}

/**
  * @brief  UART1 Clock Enable
  * @param  None
  * @retval None
  */
static void UART1_EnableClock()
{
	LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_USART1);
}

/**
  * @brief  UART1 GPIO Configure
  * @param  None
  * @retval None
  */
static void UART1_ConfigureGPIO()
{
	LL_GPIO_InitTypeDef LL_GPIO_InitStructure;
	
	LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOA);
	/**USART1 GPIO Configuration
  PA9   ------> USART1_TX
  PA10   ------> USART1_RX
  */
  LL_GPIO_InitStructure.Pin   = LL_GPIO_PIN_9;
  LL_GPIO_InitStructure.Mode  = LL_GPIO_MODE_ALTERNATE;
  LL_GPIO_InitStructure.Speed = LL_GPIO_MODE_OUTPUT_2MHz;
  LL_GPIO_InitStructure.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
	LL_GPIO_InitStructure.Pull			= LL_GPIO_PULL_UP;
  LL_GPIO_Init(GPIOA, &LL_GPIO_InitStructure);

  LL_GPIO_InitStructure.Pin  = LL_GPIO_PIN_10;
  LL_GPIO_InitStructure.Mode = LL_GPIO_MODE_FLOATING;
  LL_GPIO_Init(GPIOA, &LL_GPIO_InitStructure);
}

/**
  * @brief  UART2 Clock Enable
  * @param  None
  * @retval None
  */
static void UART2_EnableClock()
{
	LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_USART2);
}

/**
  * @brief  UART2 GPIO Configure
  * @param  None
  * @retval None
  */
static void UART2_ConfigureGPIO()
{
	LL_GPIO_InitTypeDef LL_GPIO_InitStructure;
	
	LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOA);
	
	/**USART1 GPIO Configuration
  PA2   ------> USART2_TX
  PA3   ------> USART2_RX
  */
  LL_GPIO_InitStructure.Pin = LL_GPIO_PIN_2;
  LL_GPIO_InitStructure.Mode = LL_GPIO_MODE_ALTERNATE;
  LL_GPIO_InitStructure.Speed = LL_GPIO_SPEED_FREQ_HIGH;
  LL_GPIO_InitStructure.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  LL_GPIO_Init(GPIOA, &LL_GPIO_InitStructure);

  LL_GPIO_InitStructure.Pin = LL_GPIO_PIN_3;
  LL_GPIO_InitStructure.Mode = LL_GPIO_MODE_FLOATING;
  LL_GPIO_Init(GPIOA, &LL_GPIO_InitStructure);
}

#if defined(USART3)
/**
  * @brief  UART3 Clock Enable
  * @param  None
  * @retval None
  */
static void UART3_EnableClock()
{
	LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_USART3);
}

/**
  * @brief  UART3 GPIO Configure
  * @param  None
  * @retval None
  */
static void UART3_ConfigureGPIO()
{
	LL_GPIO_InitTypeDef LL_GPIO_InitStructure;
	
	LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOB);
	
	/**USART1 GPIO Configuration
  PB10   ------> USART3_TX
  PB11   ------> USART3_RX
  */
  LL_GPIO_InitStructure.Pin = LL_GPIO_PIN_10;
  LL_GPIO_InitStructure.Mode = LL_GPIO_MODE_ALTERNATE;
  LL_GPIO_InitStructure.Speed = LL_GPIO_SPEED_FREQ_HIGH;
  LL_GPIO_InitStructure.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  LL_GPIO_Init(GPIOB, &LL_GPIO_InitStructure);

  LL_GPIO_InitStructure.Pin = LL_GPIO_PIN_11;
  LL_GPIO_InitStructure.Mode = LL_GPIO_MODE_FLOATING;
  LL_GPIO_Init(GPIOB, &LL_GPIO_InitStructure);
}
#endif

#if defined(UART4)
/**
  * @brief  UART4 Clock Enable
  * @param  None
  * @retval None
  */
static void UART4_EnableClock()
{
	LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_UART4);
}

/**
  * @brief  UART4 GPIO Configure
  * @param  None
  * @retval None
  */
static void UART4_ConfigureGPIO()
{
	LL_GPIO_InitTypeDef LL_GPIO_InitStructure;
	
	LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOC);
	
	/**USART1 GPIO Configuration
  PC10   ------> UART4_TX
  PC11   ------> UART4_RX
  */
  LL_GPIO_InitStructure.Pin = LL_GPIO_PIN_10;
  LL_GPIO_InitStructure.Mode = LL_GPIO_MODE_ALTERNATE;
  LL_GPIO_InitStructure.Speed = LL_GPIO_SPEED_FREQ_HIGH;
  LL_GPIO_InitStructure.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  LL_GPIO_Init(GPIOC, &LL_GPIO_InitStructure);

  LL_GPIO_InitStructure.Pin = LL_GPIO_PIN_11;
  LL_GPIO_InitStructure.Mode = LL_GPIO_MODE_FLOATING;
	LL_GPIO_Init(GPIOC, &LL_GPIO_InitStructure);
}
#endif

#if defined(UART5)
/**
  * @brief  UART5 Clock Enable
  * @param  None
  * @retval None
  */
static void UART5_EnableClock()
{
	LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_UART5);
}

/**
  * @brief  UART5 GPIO Configure
  * @param  None
  * @retval None
  */
static void UART5_ConfigureGPIO()
{
	LL_GPIO_InitTypeDef LL_GPIO_InitStructure;
	
	/**UART5 GPIO Configuration
  PC12   ------> UART5_TX
  PD2   ------> UART5_RX
  */
  LL_GPIO_InitStructure.Pin = LL_GPIO_PIN_12;
  LL_GPIO_InitStructure.Mode = LL_GPIO_MODE_ALTERNATE;
  LL_GPIO_InitStructure.Speed = LL_GPIO_SPEED_FREQ_HIGH;
  LL_GPIO_InitStructure.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  LL_GPIO_Init(GPIOC, &LL_GPIO_InitStructure);

  LL_GPIO_InitStructure.Pin = LL_GPIO_PIN_2;
  LL_GPIO_InitStructure.Mode = LL_GPIO_MODE_FLOATING;
  LL_GPIO_Init(GPIOD, &LL_GPIO_InitStructure);
}
#endif

/* Interrupt Handlers ----------------------------------------------------*/
//UART1 IT Handler
void USART1_IRQHandler()
{
	if (LL_USART_IsActiveFlag_RXNE(g_xUART[1].pxUARTx) && LL_USART_IsEnabledIT_RXNE(g_xUART[1].pxUARTx))
	{
		if (g_xUARTHandler[1].pFuncRxneHandler != NULL)
			g_xUARTHandler[1].pFuncRxneHandler();
		else
			LL_USART_ReceiveData8(g_xUART[1].pxUARTx);				//Clear the pending bits
	}
	
	if (LL_USART_IsActiveFlag_IDLE(g_xUART[1].pxUARTx) && LL_USART_IsEnabledIT_IDLE(g_xUART[1].pxUARTx))
	{
		if (g_xUARTHandler[1].pFuncIdleHandler != NULL)
			g_xUARTHandler[1].pFuncIdleHandler();
		//Clear Idle IT flag
		LL_USART_ClearFlag_IDLE(g_xUART[1].pxUARTx);
	}
	
	if (LL_USART_IsActiveFlag_TXE(g_xUART[1].pxUARTx) && LL_USART_IsEnabledIT_TXE(g_xUART[1].pxUARTx))
	{
		if (g_xUARTHandler[1].pFuncTxeHandler != NULL)
			g_xUARTHandler[1].pFuncTxeHandler();
	}
	
	if (LL_USART_IsActiveFlag_TC(g_xUART[1].pxUARTx) && LL_USART_IsEnabledIT_TC(g_xUART[1].pxUARTx))
	{
		if (g_xUARTHandler[1].pFuncTcHandler != NULL)
			g_xUARTHandler[1].pFuncTcHandler();
		//Clear TC IT flag
		LL_USART_ClearFlag_TC(g_xUART[1].pxUARTx);
	}
	
	if (LL_USART_IsActiveFlag_PE(g_xUART[1].pxUARTx) || LL_USART_IsActiveFlag_FE(g_xUART[1].pxUARTx) || 
		LL_USART_IsActiveFlag_NE(g_xUART[1].pxUARTx) || LL_USART_IsActiveFlag_ORE(g_xUART[1].pxUARTx))
	{
		//Other errors, Clear all error bits
		LL_USART_ClearFlag_PE(g_xUART[1].pxUARTx);
		LL_USART_ClearFlag_FE(g_xUART[1].pxUARTx);
		LL_USART_ClearFlag_NE(g_xUART[1].pxUARTx);
		LL_USART_ClearFlag_ORE(g_xUART[1].pxUARTx);
	}
}

//UART2 IT Handler
void USART2_IRQHandler()
{
	if (LL_USART_IsActiveFlag_RXNE(g_xUART[2].pxUARTx) && LL_USART_IsEnabledIT_RXNE(g_xUART[2].pxUARTx))
	{
		if (g_xUARTHandler[2].pFuncRxneHandler != NULL)
			g_xUARTHandler[2].pFuncRxneHandler();
		else
			LL_USART_ReceiveData8(g_xUART[2].pxUARTx);				//Clear the pending bits
	}
	
	if (LL_USART_IsActiveFlag_IDLE(g_xUART[2].pxUARTx) && LL_USART_IsEnabledIT_IDLE(g_xUART[2].pxUARTx))
	{
		if (g_xUARTHandler[2].pFuncIdleHandler != NULL)
			g_xUARTHandler[2].pFuncIdleHandler();
		//Clear Idle IT flag
		LL_USART_ClearFlag_IDLE(g_xUART[2].pxUARTx);
	}
	
	if (LL_USART_IsActiveFlag_TXE(g_xUART[2].pxUARTx) && LL_USART_IsEnabledIT_TXE(g_xUART[2].pxUARTx))
	{
		if (g_xUARTHandler[2].pFuncTxeHandler != NULL)
			g_xUARTHandler[2].pFuncTxeHandler();
	}
	
	if (LL_USART_IsActiveFlag_TC(g_xUART[2].pxUARTx) && LL_USART_IsEnabledIT_TC(g_xUART[2].pxUARTx))
	{
		if (g_xUARTHandler[2].pFuncTcHandler != NULL)
			g_xUARTHandler[2].pFuncTcHandler();
		//Clear TC IT flag
		LL_USART_ClearFlag_TC(g_xUART[2].pxUARTx);
	}
	
	if (LL_USART_IsActiveFlag_PE(g_xUART[2].pxUARTx) || LL_USART_IsActiveFlag_FE(g_xUART[2].pxUARTx) || 
		LL_USART_IsActiveFlag_NE(g_xUART[2].pxUARTx) || LL_USART_IsActiveFlag_ORE(g_xUART[2].pxUARTx))
	{
		//Other errors, Clear all error bits
		LL_USART_ClearFlag_PE(g_xUART[2].pxUARTx);
		LL_USART_ClearFlag_FE(g_xUART[2].pxUARTx);
		LL_USART_ClearFlag_NE(g_xUART[2].pxUARTx);
		LL_USART_ClearFlag_ORE(g_xUART[2].pxUARTx);
	}
}

//UART3 IT Handler
#if defined(USART3)
void USART3_IRQHandler()
{
	if (LL_USART_IsActiveFlag_RXNE(g_xUART[3].pxUARTx) && LL_USART_IsEnabledIT_RXNE(g_xUART[3].pxUARTx))
	{
		if (g_xUARTHandler[3].pFuncRxneHandler != NULL)
			g_xUARTHandler[3].pFuncRxneHandler();
		else
			LL_USART_ReceiveData8(g_xUART[3].pxUARTx);				//Clear the pending bits
	}
	
	if (LL_USART_IsActiveFlag_IDLE(g_xUART[3].pxUARTx) && LL_USART_IsEnabledIT_IDLE(g_xUART[3].pxUARTx))
	{
		if (g_xUARTHandler[3].pFuncIdleHandler != NULL)
			g_xUARTHandler[3].pFuncIdleHandler();
		//Clear Idle IT flag
		LL_USART_ClearFlag_IDLE(g_xUART[3].pxUARTx);
	}
	
	if (LL_USART_IsActiveFlag_TXE(g_xUART[3].pxUARTx) && LL_USART_IsEnabledIT_TXE(g_xUART[3].pxUARTx))
	{
		if (g_xUARTHandler[3].pFuncTxeHandler != NULL)
			g_xUARTHandler[3].pFuncTxeHandler();
	}
	
	if (LL_USART_IsActiveFlag_TC(g_xUART[3].pxUARTx) && LL_USART_IsEnabledIT_TC(g_xUART[3].pxUARTx))
	{
		if (g_xUARTHandler[3].pFuncTcHandler != NULL)
			g_xUARTHandler[3].pFuncTcHandler();
		//Clear TC IT flag
		LL_USART_ClearFlag_TC(g_xUART[3].pxUARTx);
	}
	
	if (LL_USART_IsActiveFlag_PE(g_xUART[3].pxUARTx) || LL_USART_IsActiveFlag_FE(g_xUART[3].pxUARTx) || 
		LL_USART_IsActiveFlag_NE(g_xUART[3].pxUARTx) || LL_USART_IsActiveFlag_ORE(g_xUART[3].pxUARTx))
	{
		//Other errors, Clear all error bits
		LL_USART_ClearFlag_PE(g_xUART[3].pxUARTx);
		LL_USART_ClearFlag_FE(g_xUART[3].pxUARTx);
		LL_USART_ClearFlag_NE(g_xUART[3].pxUARTx);
		LL_USART_ClearFlag_ORE(g_xUART[3].pxUARTx);
	}
}
#endif

//UART4 IT Handler
#if defined(UART4)
void UART4_IRQHandler()
{
	if (LL_USART_IsActiveFlag_RXNE(g_xUART[4].pxUARTx) && LL_USART_IsEnabledIT_RXNE(g_xUART[4].pxUARTx))
	{
		if (g_xUARTHandler[4].pFuncRxneHandler != NULL)
			g_xUARTHandler[4].pFuncRxneHandler();
		else
			LL_USART_ReceiveData8(g_xUART[4].pxUARTx);				//Clear the pending bits
	}
	
	if (LL_USART_IsActiveFlag_IDLE(g_xUART[4].pxUARTx) && LL_USART_IsEnabledIT_IDLE(g_xUART[4].pxUARTx))
	{
		if (g_xUARTHandler[4].pFuncIdleHandler != NULL)
			g_xUARTHandler[4].pFuncIdleHandler();
		//Clear Idle IT flag
		LL_USART_ClearFlag_IDLE(g_xUART[4].pxUARTx);
	}
	
	if (LL_USART_IsActiveFlag_TXE(g_xUART[4].pxUARTx) && LL_USART_IsEnabledIT_TXE(g_xUART[4].pxUARTx))
	{
		if (g_xUARTHandler[4].pFuncTxeHandler != NULL)
			g_xUARTHandler[4].pFuncTxeHandler();
	}
	
	if (LL_USART_IsActiveFlag_TC(g_xUART[4].pxUARTx) && LL_USART_IsEnabledIT_TC(g_xUART[4].pxUARTx))
	{
		if (g_xUARTHandler[4].pFuncTcHandler != NULL)
			g_xUARTHandler[4].pFuncTcHandler();
		//Clear TC IT flag
		LL_USART_ClearFlag_TC(g_xUART[4].pxUARTx);
	}
	
	if (LL_USART_IsActiveFlag_PE(g_xUART[4].pxUARTx) || LL_USART_IsActiveFlag_FE(g_xUART[4].pxUARTx) || 
		LL_USART_IsActiveFlag_NE(g_xUART[4].pxUARTx) || LL_USART_IsActiveFlag_ORE(g_xUART[4].pxUARTx))
	{
		//Other errors, Clear all error bits
		LL_USART_ClearFlag_PE(g_xUART[4].pxUARTx);
		LL_USART_ClearFlag_FE(g_xUART[4].pxUARTx);
		LL_USART_ClearFlag_NE(g_xUART[4].pxUARTx);
		LL_USART_ClearFlag_ORE(g_xUART[4].pxUARTx);
	}
}
#endif

//UART5 IT Handler
#if defined(UART5)
void UART5_IRQHandler()
{
	if (LL_USART_IsActiveFlag_RXNE(g_xUART[5].pxUARTx) && LL_USART_IsEnabledIT_RXNE(g_xUART[5].pxUARTx))
	{
		if (g_xUARTHandler[5].pFuncRxneHandler != NULL)
			g_xUARTHandler[5].pFuncRxneHandler();
		else
			LL_USART_ReceiveData8(g_xUART[5].pxUARTx);				//Clear the pending bits
	}
	
	if (LL_USART_IsActiveFlag_IDLE(g_xUART[5].pxUARTx) && LL_USART_IsEnabledIT_IDLE(g_xUART[5].pxUARTx))
	{
		if (g_xUARTHandler[5].pFuncIdleHandler != NULL)
			g_xUARTHandler[5].pFuncIdleHandler();
		//Clear Idle IT flag
		LL_USART_ClearFlag_IDLE(g_xUART[5].pxUARTx);
	}
	
	if (LL_USART_IsActiveFlag_TXE(g_xUART[5].pxUARTx) && LL_USART_IsEnabledIT_TXE(g_xUART[5].pxUARTx))
	{
		if (g_xUARTHandler[5].pFuncTxeHandler != NULL)
			g_xUARTHandler[5].pFuncTxeHandler();
	}
	
	if (LL_USART_IsActiveFlag_TC(g_xUART[5].pxUARTx) && LL_USART_IsEnabledIT_TC(g_xUART[5].pxUARTx))
	{
		if (g_xUARTHandler[5].pFuncTcHandler != NULL)
			g_xUARTHandler[5].pFuncTcHandler();
		//Clear TC IT flag
		LL_USART_ClearFlag_TC(g_xUART[5].pxUARTx);
	}
	
	if (LL_USART_IsActiveFlag_PE(g_xUART[5].pxUARTx) || LL_USART_IsActiveFlag_FE(g_xUART[5].pxUARTx) || 
		LL_USART_IsActiveFlag_NE(g_xUART[5].pxUARTx) || LL_USART_IsActiveFlag_ORE(g_xUART[5].pxUARTx))
	{
		//Other errors, Clear all error bits
		LL_USART_ClearFlag_PE(g_xUART[5].pxUARTx);
		LL_USART_ClearFlag_FE(g_xUART[5].pxUARTx);
		LL_USART_ClearFlag_NE(g_xUART[5].pxUARTx);
		LL_USART_ClearFlag_ORE(g_xUART[5].pxUARTx);
	}
}
#endif

